/**
 *  Copyright (c) 2010-2011, Monash e-Research Centre
 * (Monash University, Australia)
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 * * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 * * Neither the name of the Monash University nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
package edu.monash.historyofadoption;

/** 
 * For creating Confluence pages, setting permissions on them and
 * uploading attachments to them. Uses XML-RPC.
 *
 * @author Grischa Meyer
 * @author Steve Androulakis
 */
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Properties;
import java.util.Vector;

import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;

public class ConfluenceUploader {

	// Configuration
	private String serverHostNameOrIP;
	private String serverPort;
	private String xmlrpcBaseDir;
	private String username;
	private String password;
	private String spaceKey;
	private String parentPageTitle;
	private String protocol;

	private String methodPrefix;

	String authToken;
	XmlRpcClient client;
	
	public ConfluenceUploader(String username, String password) throws XmlRpcException, IOException {
		this.username = username;
		this.password = password;

		InputStream propfile = ListAssets.class.getClassLoader()
		.getResourceAsStream("setup.properties");

		Properties props = new Properties();
		props.load(propfile);

		this.serverHostNameOrIP =  props.getProperty("confluence.serverHostNameOrIP");
		this.serverPort =  props.getProperty("confluence.serverPort");
		this.xmlrpcBaseDir =  props.getProperty("confluence.xmlrpcBaseDir");
		this.spaceKey =  props.getProperty("confluence.spaceKey");
		this.parentPageTitle = props.getProperty("confluence.parentPageTitle");
		this.methodPrefix =  props.getProperty("confluence.methodPrefix");
		this.protocol = props.getProperty("confluence.protocol");
		//System.out.println(this.xmlrpcBaseDir);
		//System.out.println(this.methodPrefix);
		setupConnection();
	}	
	
	private void setupConnection() throws XmlRpcException,
			MalformedURLException {
		XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
		String confluenceURL = protocol.trim() + "://" + this.serverHostNameOrIP.trim();
		if (!this.serverPort.trim().equals("")) confluenceURL = confluenceURL + ":" + this.serverPort.trim();
		confluenceURL = confluenceURL + this.xmlrpcBaseDir.trim();
		config.setServerURL(new URL(confluenceURL));
		this.client = new XmlRpcClient();
		this.client.setConfig(config);
		Object[] params = new Object[] { this.username, this.password };
		this.authToken = (String) this.client.execute(this.methodPrefix + "login", params);
		// System.out.println(authToken);

	}

  /**
   * Uploads file data as an attachment to a Confluence page
   *
   * @param pageID The numerical ID of the target Confluence page
   * @param fileName The target name for the attachment
   * @param contentType the MIME type of the file
   * @param comment Used as the attachment comment on the Confluence page
   * @param A bytestream representation of the attachment data to be uploaded
   * @exception XmlRpcException If the XML-RPC call is invalid for any reason
   */
	HashMap attachStuff(String pageID, String fileName,
			String contentType, String comment, byte[] data)
			throws XmlRpcException {
		HashMap attachment = new HashMap(3);
		attachment.put("fileName", fileName);
		attachment.put("contentType", contentType);
		attachment.put("comment", comment);
		HashMap newAttachement = (HashMap) this.client.execute(this.methodPrefix
				+ "addAttachment", new Object[] { this.authToken, pageID,
				attachment, data });
		return newAttachement;

	}

	  /**
	   * Creates a new Confluence page in the space defined by confluence.spaceKey in
	   * setup.properties
	   *
	   * @param title The title of the new page
	   * @param content The text content of the page
	   * @param username The username to assign as the page creator
	   * @exception XmlRpcException If the XML-RPC call is invalid for any reason
	   * @exception MalformedURLException If the destination URL is invalid
	   */
	HashMap createPage(String title, String content, String username)
			throws MalformedURLException, XmlRpcException {

		// get parent page id
		HashMap parentPage = (HashMap) client.execute( this.methodPrefix + "getPage", 
				new Object[] { authToken, spaceKey, parentPageTitle} );
		String parentPageID = (String) parentPage.get("id");
		// create Page Map
		HashMap page = new HashMap(5);
		page.put("space", spaceKey);
		page.put("title", title);
		page.put("content", content);
		page.put("parentId", parentPageID);
		// System.out.println(page);
		HashMap returnedPage = (HashMap) client.execute(this.methodPrefix
				+ "storePage", new Object[] { authToken, page });
		// set Permissions
		String newPageID = (String) returnedPage.get("id");
		
		addPermissionToPage(username, newPageID, "View");
		addPermissionToPage(username, newPageID, "Edit");
		
		return returnedPage;
	}

  /**
   * Creates a new Confluence page in the space defined by confluence.spaceKey in
   * setup.properties
   *
   * @param newPageID The ID of a page
   * @param username The username to assign as the page creator
   * @param permType A string representation of the permission to assign eg. "View" or "Edit"
   * @exception XmlRpcException If the XML-RPC call is invalid for any reason
   * @exception MalformedURLException If the destination URL is invalid
   */	
	private void addPermissionToPage(String username, String newPageID,
			String permType) throws XmlRpcException {
		HashMap permissions = new HashMap(3);
		permissions.put("type", permType);
		permissions.put("userName", username);
		//permissions.put("groupName", null);
		Vector permVector = new Vector();
		permVector.add(permissions);
		client.execute(this.methodPrefix + "setContentPermissions",
				new Object[] {authToken, newPageID, permType, permVector});
	}

	  /**
	   * Adds labels (like tags) to a Confluence page
	   *
	   * @param pageID The ID of a page
	   * @param labels A comma separated string of labels to add
	   * @exception XmlRpcException If the XML-RPC call is invalid for any reason
	   */		
	void addLabelToPage(Object pageID, String labels) throws XmlRpcException {
		client.execute(this.methodPrefix + "addLabelByName",
				new Object[] {authToken, labels, pageID});
	}
	
}
